# coding=utf8
import re
import time
import json
import redis
from datetime import datetime

from twisted.internet import reactor, task, protocol
from twisted.internet import defer, threads
from twisted.internet.protocol import Protocol, error, Factory
from twisted.protocols.basic import LineReceiver
from dbhelper import insert_iot_record

r = redis.Redis(host='redisdb',port=6379,db=0)

@defer.inlineCallbacks
def hello():
    print('hello world!')
def getCurrentStrTime():
    return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

class GasServerProtocol(LineReceiver):

    def __init__(self, factory):
        self.id = ''
        self.factory = factory
        self.last_iot_time = datetime.now()
        self.fisrt_recv_flag = True

    def connectionMade(self):
        print(
            "[%s]:  %s连接到服务器端。" %
            (getCurrentStrTime(), self.transport.getPeer()))
        self.sendLine("$99'".encode('utf-8'))

    def connectionLost(self, reason):
        if self.id in self.factory.clients:
            del self.factory.clients[self.id]
            print("[%s]:ID %s 下线" % (getCurrentStrTime(), self.id))
        print(
            "[%s]:  %s断开了连接,原因是%s" %
            (getCurrentStrTime(),
             self.transport.getPeer(),
             reason))
    def insert_iot_record_cb(self, result):
        print(result)
        self.last_iot_time = datetime.now()
        self.fisrt_recv_flag = False
    def lineReceived(self, data):
        data = data.decode('utf-8')
        tmpstr = ("[%s]: 收到数据 %s") % (getCurrentStrTime(), data)
        print(tmpstr)
        if(re.match("\$\d{2}\$", data)):
            self.id = str(data[1:3])
            dicttmp = {}
            dicttmp['handle'] = self
            dicttmp['timestamp'] = time.time()
            self.factory.clients[self.id] = dicttmp
            print("[%s]:ID %s 注册成功" % (getCurrentStrTime(), self.id))
        if(re.match('@\d{2}\D\w{12}\d{2}',data)):
            if(data[3] == 'D'):
                print(u'接收到1条命令！\r\n')
                volttmp = (int(data[4:8],16)/1000.0)
                temperature = (int(data[8:12],16)/10.0)
                humidity = (int(data[12:16],16)/10.0)
                # lightness = xxxxx
                dicttmp = {}
                dicttmp['collecttime'] = getCurrentStrTime()
                dicttmp['voltage'] = volttmp
                dicttmp['temperature'] = temperature
                dicttmp['humidity'] = humidity
                # dicttmp['lightness'] = xxx
                dicttmp['id'] = self.id
                r.set(self.id, json.dumps(dicttmp))
                print(r.get(self.id))
            current_time = datetime.now()
            if((current_time - self.last_iot_time).seconds >= 5 * 60 or self.fisrt_recv_flag):
                insert_iot_record( r.get(self.id)).addCallback(
                    self.insert_iot_record_cb)

class GasServerFactory(Factory):

    def __init__(self):
        self.clients = {}  # maps clients ids to GasServerProtocol instances
        self._lc = task.LoopingCall(self.send_to_clients)
        self._lc.start(3,now=False)

    def buildProtocol(self, addr):
        return GasServerProtocol(self)
    def send_to_clients(self):
        for client_addr in self.clients :
            self.clients[client_addr]['handle'].sendLine('@12d000000'.encode('utf-8'))
    @defer.inlineCallbacks
    def receive_from_mq(self):
        # print('in mq')
        try:
            data = yield r.rpop('front_tcp')
            if data and data != '':
                print(u'接收到1条控制命令！%s\r\n' % (data))
                self.process_data_from_mq(data)
        except:
            pass

    def process_data_from_mq(self, data):
        loads_data = (json.loads(data))
        command = loads_data.get('command')
        addr = (loads_data.get('addr'))
        mydata = loads_data.get('data')
        send_data = '@%s%s%s01' % (addr,command,mydata)
        send_data = send_data.encode('utf-8')
        self.clients[addr]['handle'].sendLine(send_data)

def startMoniter():
    print("[%s]启动监控服务" % getCurrentStrTime())
    cf = GasServerFactory()
    task_receive_data_from_mq = task.LoopingCall(cf.receive_from_mq)
    task_receive_data_from_mq.start(0.1, now=False)
    reactor.callWhenRunning(cf.receive_from_mq)

    reactor.listenTCP(8234, cf)
    cf.receive_from_mq()
    #hello()
    reactor.run()

def stopMoniter():
    print("[%s]停止监控服务" % getCurrentStrTime())
    try:
        reactor.crash()
    except RuntimeError:
        return defer.fail()
    else:
        return defer.succeed(None)

startMoniter()
